package br.org.bertol.mestrado.engine.optimisation.sls;

import java.util.Collections;

import org.apache.log4j.Logger;

import br.org.bertol.mestrado.Verify;
import br.org.bertol.mestrado.engine.optimisation.Unit;
import br.org.bertol.mestrado.engine.optimisation.moo.ParetoDominace;

public class IteratedLocalSearch<U extends Unit> extends
        StochasticLocalSearch<U> {

    public IteratedLocalSearch(final Verify verify, final U unit,
        final int breakCondition) {

        super(verify, breakCondition, unit);

    }

    @SuppressWarnings("unchecked")
    @Override
    public void evaluate() throws Exception {

        betterUnit = (U) startUnit.clone();

        Logger.getLogger(getClass())
                .info(
                      "ILS START ----------------------------------------- : "
                + startUnit);

        int rangeSwap = 1;

        int iter = 0;

        int MelhorIter = 0;

        // loop principal
        while (iter - MelhorIter < numIteracoes) {
            iter++;

            int num_trocas_max = rangeSwap + 1;

            int num_trocas = 0;

            U candidato_s = (U) betterUnit.clone();

            // quantidade de perturbar��es que ser�o realizadas
            while (num_trocas < num_trocas_max) {
                num_trocas++;

                int x1 = (int) (Math.random() * verify.getClasses().size());

                int x2 = x1;

                while (x1 == x2)
                    x2 = (int) (Math.random() * verify.getClasses().size());

                Collections.swap(candidato_s.getRoute(), x1, x2);

                hillClimbing.setPath(candidato_s);

                hillClimbing.runHillClimbing();

                U candidato_ss = (U) hillClimbing.getBestPath().clone();

                if (paretoDominace.compare(candidato_ss.getHeight(),
                                           candidato_s.getHeight()) == ParetoDominace.LEFT_DOMINE) {

                    candidato_ss.update();

                    num_trocas = 0;

                    rangeSwap = 1;

                    betterUnit = (U) candidato_ss.clone();

                    candidato_s = (U) candidato_ss.clone();

                    MelhorIter = iter;

                    Logger
                            .getLogger(getClass())
                            .debug(
                                   "Caminho melhor encontrado ------------------------ : "
                                           + candidato_ss);
                }

                hillClimbing.reset();
                num_trocas++;

            }

            rangeSwap++;
        }

        Logger.getLogger(getClass())
                .info(
                      "ILS STOP ------------------------------------------ : "
                + betterUnit);
    }
}
